/*
 * NAME:
 *   msmtp-notify - notify if msmtp sent failed
 *
 * RCSID:
 *   Copyright (C) 2011 Du Yang <duyang.seu@gmail.com>
 *   All RIghts Reserved
 *   $Id: msmtp-notify.c 1.7 2011-11-02 16:30:50+80 duyang Exp $
 *
 * SYNTAX:
 *   msmtp-notify  [ -i interval ] [ -o ] [ -t ] [ -r /path/to/notify.log ] [ -l /path/to/msmtp.log ]
 *   msmtp-notify  -v
 *   msmtp-notify  -h
 *
 * DESCRIPTION:
 *   See the manual.
 *
 * LICENCE:
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2
 *   of the License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the 
 *
 *       Free Software Foundation, Inc.,
 *       59 Temple Place - Suite 330,
 *       Boston, MA  02111-1307, USA.
 *
 *   You can also find at the GNU General Public License on the web:
 *
 *       <http://www.gnu.org/copyleft/gpl.html>
 */

#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

static char * const rcsid[] = {
  "Copyright (C) 2011 Du Yang <duyang.seu@gmail.com>",
  "All Rights Reserved",
  "$Id: msmtp-notify.c 1.7 2011-11-03 23:30:50+80 Exp $"
};

static void setup(int, char **, int *, int *, int *, char **, char ** );
static void usage(char *);
static void version(void);


int
main(int argc, char **argv)
{
  int interval = 1;
  int use_osd = 0;
  int use_osd_wrapper = 0;
  char *root_tail = "";
  char *msmtplog = "./msmtp.log";
  time_t last_check = 0, now;
  struct tm *ptr;
  struct stat sb;
  char buffer[1024];
  int fd, old_size = 0;
  int pipe_fd[2];
  char month_str[12][4]={"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  pid_t pid;

  setup(argc, argv, &interval, &use_osd, &use_osd_wrapper, &root_tail, &msmtplog);

  while(1) {
    char *p = NULL;
    time(&now);
    ptr = localtime(&now);
    if (stat(msmtplog, &sb) == 0)
      if (sb.st_mtime <= last_check) {
	sleep(interval);
	continue;
      }
    if ((fd = open(msmtplog, O_RDONLY, 0400)) < 0)
      err(1, "open(%s)", msmtplog);
    if (old_size == 0 || old_size >= sb.st_size)
      lseek(fd, -20, SEEK_END);
    else
      lseek(fd, -1*(sb.st_size-old_size+1), SEEK_END);
    memset(buffer, '\0', sizeof(buffer));
    int r = 0;
    r = read(fd, buffer, sizeof(buffer));
    close(fd);
    // replace '\n' to '='
    int i, j;
    for (i = 0; i < sizeof(buffer); i++)
      if (buffer[i]=='\n')
	buffer[i]='=';
    //printf("%s\n", buffer);
    p = strtok(buffer,"=");
    //printf("%s\n", p);
    i = 0;
    j = 0;
    while (1) {
      //p = strtok(NULL,"=");
      if (!strncmp(p, "EX_", 3) && strncmp(p, "EX_OK", 5))
	i++;
      if (!strncmp(p, "EX_", 3) && !strncmp(p, "EX_OK", 5))
	j++;
      //printf("%s\n", p);
      p = strtok(NULL,"=");
      if(!p)
	break;
    }

    if(i > 0 && old_size) {
      char notify_cmd[256];
      memset(notify_cmd, '\0', sizeof(256));
      if (!use_osd) {
	if (use_osd_wrapper) {
	  char * fifo = "/tmp/osd-wrapper";
	  int fd;
	  if ((fd = open(fifo, O_WRONLY)) >= 0) {
	    FILE* in = fdopen(fd, "w");
	    sprintf(notify_cmd, "%s %d %02d:%02d - %d mail%s sent *FAILED*.\n", month_str[ptr->tm_mon], ptr->tm_mday, ptr->tm_hour, ptr->tm_min, i, (i != 1 ? "s" : " "));
	    fprintf(in, "%s", notify_cmd);
	    fflush(in);
	    fclose(in);
	    close(fd);
	  }
	}
	else if (strcmp(root_tail, "")) {
	  int fd;
	  if ((fd = open(root_tail, O_CREAT | O_WRONLY | O_APPEND, 0600)) >= 0) {
	    sprintf(notify_cmd, "%s %d %02d:%02d - %d mail%s sent *FAILED*.\n", month_str[ptr->tm_mon], ptr->tm_mday, ptr->tm_hour, ptr->tm_min, i, (i != 1 ? "s" : " "));
	    FILE* in = fdopen(fd, "w");
	    fprintf(in, "%s", notify_cmd);
	    fflush(in);
	    fclose(in);
	    close(fd);
	  }
	}
	else {
	  sprintf(notify_cmd, "export DISPLAY=:0; /usr/bin/notify-send -t %d -i /usr/share/pixmaps/xmms2-48.png \"Mail Sent *FAILED*\" \"You have %d mail(s) sent *FAILED*. (%02d:%02d %s %d)\"", interval*1000, i, ptr->tm_hour, ptr->tm_min, month_str[ptr->tm_mon], ptr->tm_mday);
	  r = system(notify_cmd);
	}
      }
      else {
	if (pipe(pipe_fd) == -1) {
	  perror("Error: failed to create pipe\n");
	  exit(1);
	}

	pid = fork();

	if (pid == 0) {
	  if (dup2(pipe_fd[0], 0) == -1) {
	    perror("Error: dup failed\n");
	    exit(0);
	  }
	  close(pipe_fd[0]);
	  close(pipe_fd[1]);

	  if (execl("/usr/bin/osd_cat", "osd_cat", "-p", "bottom", "-A", "right", "-c", "blue", "-o", "10", "-i", "50", "-f", "-*-lucidatypewriter-medium-*-*-*-20-*-*-*-*-*-*-*", "-d", "10", NULL) < 0) {
	    printf("Error: failed to fork osd_cat\n");
	  }
	}
	else {
	  FILE* in = fdopen(pipe_fd[1], "w");
	  close(pipe_fd[0]);
	  sprintf(notify_cmd, "%s %d %02d:%02d - %d mail%s sent *FAILED*.\n", month_str[ptr->tm_mon], ptr->tm_mday, ptr->tm_hour, ptr->tm_min, i, (i != 1 ? "s" : " "));

	  fprintf(in, "%s", notify_cmd);

	  fflush(in);
	  fclose(in);
	  close(pipe_fd[1]);
	}
      }

    }

    if(j > 0 && old_size) {
      char notify_cmd[256];
      memset(notify_cmd, '\0', sizeof(notify_cmd));
      if (!use_osd) {
	if (use_osd_wrapper) {
	  char * fifo = "/tmp/osd-wrapper";
	  int fd = open(fifo, O_WRONLY);
	  if ((fd = open(fifo, O_WRONLY)) >= 0) {
	    FILE* in = fdopen(fd, "w");
	    sprintf(notify_cmd, "%s %d %02d:%02d - %d mail%s sent SUCCESSfully.\n", month_str[ptr->tm_mon], ptr->tm_mday, ptr->tm_hour, ptr->tm_min, j, (j != 1 ? "s" : " "));
	    fprintf(in, "%s", notify_cmd);
	    fflush(in);
	    fclose(in);
	    close(fd);
	  }
	}
	else if (strcmp(root_tail, "")) {
	  int fd;
	  umask(0077);
	  if ((fd = open(root_tail, O_CREAT | O_WRONLY | O_APPEND, 0600)) >= 0) {
	    sprintf(notify_cmd, "%s %d %02d:%02d - %d mail%s sent SUCCESSfully.\n", month_str[ptr->tm_mon], ptr->tm_mday, ptr->tm_hour, ptr->tm_min, j, (j != 1 ? "s" : " "));
	    FILE* in = fdopen(fd, "w");
	    fprintf(in, "%s", notify_cmd);
	    fflush(in);
	    fclose(in);
	    close(fd);
	  }
	}
	else {
	  sprintf(notify_cmd, "export DISPLAY=:0; /usr/bin/notify-send -t %d -i /usr/share/pixmaps/xmms2-48.png \"Mail Sent Successfully\" \"You have %d mail(s) sent successfully. (%02d:%02d %s %d)\"", interval*1000, j, ptr->tm_hour, ptr->tm_min, month_str[ptr->tm_mon], ptr->tm_mday);
	  r = system(notify_cmd);
	}
      }
      else {
	if (pipe(pipe_fd) == -1) {
	  perror("Error: failed to create pipe\n");
	  exit(1);
	}
	pid = fork();

	if (pid == 0) {
	  if (dup2(pipe_fd[0], 0) == -1) {
	    perror("Error: dup failed\n");
	    exit(0);
	  }
	  close(pipe_fd[0]);
	  close(pipe_fd[1]);

	  if (execl("/usr/bin/osd_cat", "osd_cat", "-p", "bottom", "-A", "right", "-c", "blue", "-o", "10", "-i", "50", "-f", "-*-lucidatypewriter-medium-*-*-*-20-*-*-*-*-*-*-*", "-d", "10", NULL) < 0) {
	    printf("Error: failed to fork osd_cat\n");
	  }
	}
	else {
	  FILE* in = fdopen(pipe_fd[1], "w");
	  close(pipe_fd[0]);
	  sprintf(notify_cmd, "%s %d %02d:%02d - %d mail%s sent SUCCESSfully.\n", month_str[ptr->tm_mon], ptr->tm_mday, ptr->tm_hour, ptr->tm_min, j, (j != 1 ? "s" : " "));

	  fprintf(in, "%s", notify_cmd);
	  fflush(in);
	  fclose(in);
	  close(pipe_fd[1]);

	}
      }

    }

    //fprintf(in, "");
    sleep(interval);
    last_check = now;
    old_size = sb.st_size;
    //  }
  }
  /* NOT_REACHED */
  close(pipe_fd[1]);
  return 0;
}


static void
setup(int argc, char **argv, int *interval, int *use_osd, int *use_osd_wrapper, char **root_tail, char **msmtplog)
{
  int c;

  while ((c = getopt(argc, argv, "tovi:r:l:h")) != -1)
    switch (c) {
    case 'v':
      version();
      exit(0);
    case 'i':
      *interval = atoi(optarg);
      break;
    case 'l':
      *msmtplog = optarg;
      break;
    case 't':
      *use_osd = 1;
      break;
    case 'o':
      *use_osd_wrapper = 1;
      break;
    case 'r':
      *root_tail = optarg;
      break;
    case 'h':
    case '?':
    default:
      usage(argv[0]);
    }
  if (*interval <= 0)
    errx(1, "interval must be a positive integer");
  if (optind < argc)
    usage(argv[0]);
  if (argc == 1)
    usage(argv[0]);
}


static void
usage(char *progname)
{
  version();
  fprintf(stderr, "usage:    %s  ", progname);
  fprintf(stderr, "[ -i interval ]  [ -o ] [ -t ] [ -r /path/to/notify.log ] [ -l msmtplog ]\n");
  fprintf(stderr, "defaults: -i 1 -l ./msmtp.log\n");
  exit(2);
}


static void
version(void)
{
  printf("%s\n%s\n%s\n", rcsid[0], rcsid[1], rcsid[2]);
}
